/**
 * 小球跳动可视化器
 */
class BouncingBallsVisualizer extends VisualizerInterface {
    constructor(canvas, ctx) {
        super(canvas, ctx);
        this.balls = [];
        this.gravity = 0.5;
        this.bounce = 0.8;
        this.ground = 0;
    }

    getInfo() {
        return {
            name: 'Bouncing Balls',
            description: '小球跳动音乐可视化',
            author: 'AudioNN',
            version: '1.0.0',
            category: 'physics'
        };
    }

    getDefaultSettings() {
        return {
            ...super.getDefaultSettings(),
            ballCount: 64,
            minBallSize: 5,
            maxBallSize: 25,
            gravityStrength: 0.5,
            bounceDecay: 0.8,
            colorMode: 'frequency', // frequency, rainbow, intensity
            showTrails: true,
            showConnections: false,
            groundHeight: 50,
            airResistance: 0.99
        };
    }

    getConfigurableParams() {
        return [
            ...super.getConfigurableParams(),
            {
                key: 'ballCount',
                label: '小球数量',
                type: 'range',
                min: 16,
                max: 128,
                step: 8,
                default: 64
            },
            {
                key: 'gravityStrength',
                label: '重力强度',
                type: 'range',
                min: 0.1,
                max: 1.0,
                step: 0.1,
                default: 0.5
            },
            {
                key: 'bounceDecay',
                label: '反弹衰减',
                type: 'range',
                min: 0.5,
                max: 0.95,
                step: 0.05,
                default: 0.8
            },
            {
                key: 'colorMode',
                label: '颜色模式',
                type: 'select',
                options: [
                    { value: 'frequency', label: '频率色彩' },
                    { value: 'rainbow', label: '彩虹渐变' },
                    { value: 'intensity', label: '强度色彩' }
                ],
                default: 'frequency'
            },
            {
                key: 'showTrails',
                label: '显示轨迹',
                type: 'boolean',
                default: true
            },
            {
                key: 'showConnections',
                label: '显示连线',
                type: 'boolean',
                default: false
            }
        ];
    }

    init(config = {}) {
        super.init(config);
        this.updateDimensions();
        this.initializeBalls();
        return this;
    }

    updateDimensions() {
        const width = this.canvas.width / window.devicePixelRatio;
        const height = this.canvas.height / window.devicePixelRatio;
        this.ground = height - this.settings.groundHeight;
        this.gravity = this.settings.gravityStrength;
        this.bounce = this.settings.bounceDecay;
    }

    initializeBalls() {
        this.balls = [];
        const width = this.canvas.width / window.devicePixelRatio;
        
        for (let i = 0; i < this.settings.ballCount; i++) {
            this.balls.push({
                x: (i + 0.5) * (width / this.settings.ballCount),
                y: this.ground - 20,
                vx: 0,
                vy: 0,
                radius: this.settings.minBallSize,
                baseRadius: this.settings.minBallSize + (this.settings.maxBallSize - this.settings.minBallSize) * Math.random(),
                intensity: 0,
                frequency: i,
                trail: [],
                lastBounceTime: 0,
                bounceCount: 0,
                energy: 0
            });
        }
    }

    render(frequencyData, cachedData = null, currentTime = 0) {
        // 清除画布或添加拖尾效果
        if (this.settings.showTrails) {
            this.ctx.fillStyle = 'rgba(0, 0, 0, 0.15)';
            const width = this.canvas.width / window.devicePixelRatio;
            const height = this.canvas.height / window.devicePixelRatio;
            this.ctx.fillRect(0, 0, width, height);
        } else {
            this.clearCanvas();
        }

        const dataToUse = cachedData || frequencyData;
        if (!dataToUse) return;

        // 绘制地面
        this.drawGround();

        // 更新小球物理
        this.updateBalls(dataToUse);

        // 绘制连接线（如果启用）
        if (this.settings.showConnections) {
            this.drawConnections();
        }

        // 绘制小球轨迹
        if (this.settings.showTrails) {
            this.drawTrails();
        }

        // 绘制小球
        this.drawBalls();

        // 绘制频谱信息
        this.drawFrequencyInfo(dataToUse);
    }

    updateBalls(frequencyData) {
        const dataPerBall = frequencyData.length / this.balls.length;

        this.balls.forEach((ball, index) => {
            // 获取对应的频谱数据
            const dataIndex = Math.floor(index * dataPerBall);
            const intensity = frequencyData[dataIndex] / 255;
            ball.intensity = intensity;

            // 根据音频强度调整小球
            ball.energy = intensity * this.settings.sensitivity;
            ball.radius = ball.baseRadius * (1 + ball.energy * 0.5);

            // 音频触发跳跃
            if (ball.energy > 0.3 && ball.y >= this.ground - ball.radius - 5) {
                const jumpForce = ball.energy * 15;
                ball.vy = -jumpForce;
                ball.lastBounceTime = Date.now();
                ball.bounceCount++;
            }

            // 物理更新
            ball.vy += this.gravity;
            ball.vx *= this.settings.airResistance;
            ball.vy *= this.settings.airResistance;

            // 位置更新
            ball.x += ball.vx;
            ball.y += ball.vy;

            // 边界碰撞检测
            const width = this.canvas.width / window.devicePixelRatio;
            
            // 水平边界
            if (ball.x - ball.radius < 0) {
                ball.x = ball.radius;
                ball.vx = -ball.vx * this.bounce;
            } else if (ball.x + ball.radius > width) {
                ball.x = width - ball.radius;
                ball.vx = -ball.vx * this.bounce;
            }

            // 地面碰撞
            if (ball.y + ball.radius > this.ground) {
                ball.y = this.ground - ball.radius;
                ball.vy = -ball.vy * this.bounce;
                
                // 添加一些随机性
                ball.vx += (Math.random() - 0.5) * 2;
            }

            // 更新轨迹
            if (this.settings.showTrails) {
                ball.trail.push({
                    x: ball.x,
                    y: ball.y,
                    radius: ball.radius,
                    intensity: ball.intensity,
                    time: Date.now()
                });

                // 限制轨迹长度
                if (ball.trail.length > 20) {
                    ball.trail.shift();
                }

                // 清理过期轨迹点
                const now = Date.now();
                ball.trail = ball.trail.filter(point => now - point.time < 2000);
            }
        });
    }

    drawGround() {
        const width = this.canvas.width / window.devicePixelRatio;
        const height = this.canvas.height / window.devicePixelRatio;

        // 绘制地面
        const gradient = this.ctx.createLinearGradient(0, this.ground, 0, height);
        gradient.addColorStop(0, 'rgba(100, 100, 100, 0.3)');
        gradient.addColorStop(1, 'rgba(50, 50, 50, 0.8)');

        this.ctx.fillStyle = gradient;
        this.ctx.fillRect(0, this.ground, width, height - this.ground);

        // 绘制地面线
        this.ctx.strokeStyle = 'rgba(200, 200, 200, 0.5)';
        this.ctx.lineWidth = 2;
        this.ctx.beginPath();
        this.ctx.moveTo(0, this.ground);
        this.ctx.lineTo(width, this.ground);
        this.ctx.stroke();
    }

    drawConnections() {
        const connectionDistance = 100;
        
        for (let i = 0; i < this.balls.length; i++) {
            for (let j = i + 1; j < this.balls.length; j++) {
                const ball1 = this.balls[i];
                const ball2 = this.balls[j];
                
                const dx = ball2.x - ball1.x;
                const dy = ball2.y - ball1.y;
                const distance = Math.sqrt(dx * dx + dy * dy);
                
                if (distance < connectionDistance) {
                    const opacity = (1 - distance / connectionDistance) * 0.3;
                    const avgIntensity = (ball1.intensity + ball2.intensity) / 2;
                    
                    this.ctx.strokeStyle = `rgba(255, 255, 255, ${opacity * avgIntensity})`;
                    this.ctx.lineWidth = 1;
                    this.ctx.beginPath();
                    this.ctx.moveTo(ball1.x, ball1.y);
                    this.ctx.lineTo(ball2.x, ball2.y);
                    this.ctx.stroke();
                }
            }
        }
    }

    drawTrails() {
        this.balls.forEach(ball => {
            if (ball.trail.length < 2) return;

            this.ctx.strokeStyle = this.getBallColor(ball, 0.3);
            this.ctx.lineWidth = 2;
            this.ctx.beginPath();

            ball.trail.forEach((point, index) => {
                const alpha = index / ball.trail.length;
                this.ctx.globalAlpha = alpha * point.intensity;
                
                if (index === 0) {
                    this.ctx.moveTo(point.x, point.y);
                } else {
                    this.ctx.lineTo(point.x, point.y);
                }
            });

            this.ctx.stroke();
            this.ctx.globalAlpha = 1.0;
        });
    }

    drawBalls() {
        this.balls.forEach(ball => {
            const color = this.getBallColor(ball);
            
            // 绘制阴影
            this.ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
            this.ctx.beginPath();
            this.ctx.ellipse(
                ball.x + 3,
                this.ground + 3,
                ball.radius * 0.8,
                ball.radius * 0.3,
                0, 0, Math.PI * 2
            );
            this.ctx.fill();

            // 绘制发光效果
            if (ball.intensity > 0.2) {
                this.ctx.shadowColor = color;
                this.ctx.shadowBlur = ball.intensity * 20;
            }

            // 绘制主球体
            this.ctx.fillStyle = color;
            this.ctx.beginPath();
            this.ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
            this.ctx.fill();

            // 绘制高光
            const highlightColor = `rgba(255, 255, 255, ${ball.intensity * 0.8})`;
            this.ctx.fillStyle = highlightColor;
            this.ctx.beginPath();
            this.ctx.arc(
                ball.x - ball.radius * 0.3,
                ball.y - ball.radius * 0.3,
                ball.radius * 0.2,
                0, Math.PI * 2
            );
            this.ctx.fill();

            // 重置阴影
            this.ctx.shadowBlur = 0;

            // 绘制强度环
            if (ball.intensity > 0.4) {
                this.ctx.strokeStyle = color;
                this.ctx.lineWidth = 2;
                this.ctx.globalAlpha = ball.intensity * 0.5;
                this.ctx.beginPath();
                this.ctx.arc(ball.x, ball.y, ball.radius + 5, 0, Math.PI * 2);
                this.ctx.stroke();
                this.ctx.globalAlpha = 1.0;
            }
        });
    }

    drawFrequencyInfo(frequencyData) {
        // 绘制频率条（底部小条）
        const width = this.canvas.width / window.devicePixelRatio;
        const barWidth = width / frequencyData.length;
        const maxBarHeight = 30;

        for (let i = 0; i < frequencyData.length; i += 4) { // 每4个取一个，减少绘制量
            const intensity = frequencyData[i] / 255;
            const barHeight = intensity * maxBarHeight;
            
            const color = this.getFrequencyColor(i, frequencyData.length, intensity);
            this.ctx.fillStyle = color;
            this.ctx.fillRect(
                i * barWidth,
                this.ground + this.settings.groundHeight - barHeight,
                barWidth * 4,
                barHeight
            );
        }
    }

    getBallColor(ball, alpha = 1.0) {
        const intensity = ball.intensity;
        
        switch (this.settings.colorMode) {
            case 'frequency':
                const hue = (ball.frequency / this.balls.length) * 360;
                const saturation = 80 + intensity * 20;
                const lightness = 40 + intensity * 40;
                return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;

            case 'rainbow':
                const rainbowHue = (ball.frequency / this.balls.length + Date.now() * 0.0001) % 1 * 360;
                return `hsla(${rainbowHue}, 90%, ${50 + intensity * 30}%, ${alpha})`;

            case 'intensity':
                const red = Math.floor(255 * intensity);
                const green = Math.floor(100 + 155 * intensity);
                const blue = Math.floor(50 + 100 * intensity);
                return `rgba(${red}, ${green}, ${blue}, ${alpha})`;

            default:
                return `rgba(102, 126, 234, ${alpha})`;
        }
    }

    getFrequencyColor(index, total, intensity) {
        const hue = (index / total) * 360;
        const alpha = intensity * 0.8;
        return `hsla(${hue}, 70%, 60%, ${alpha})`;
    }

    resize(width, height) {
        this.updateDimensions();
        // 重新定位小球到地面
        this.balls.forEach((ball, index) => {
            ball.x = (index + 0.5) * (width / this.settings.ballCount);
            if (ball.y > this.ground - ball.radius) {
                ball.y = this.ground - ball.radius;
            }
        });
    }
}

// 注册可视化器到全局注册表
if (typeof window !== 'undefined') {
    if (!window.visualizerRegistrations) {
        window.visualizerRegistrations = [];
    }
    window.visualizerRegistrations.push({
        id: 'bouncing-balls',
        class: BouncingBallsVisualizer
    });
}

window.BouncingBallsVisualizer = BouncingBallsVisualizer;
